package com.chenyun.rpc.dubbo.satoken.filter;

import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.context.SaTokenContextDefaultImpl;
import cn.dev33.satoken.same.SaSameUtil;
import cn.dev33.satoken.stp.StpUtil;
import com.chenyun.satoken.starter.util.SaUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.service.GenericService;

/**
 * dubbo3的过滤器
 * 移植 sa-token-dubbo3 中的代码到此处
 * 增加自定义其他功能
 *
 * @author: Lonni
 * @date: 2024/1/22 0022 16:38
 */
@Slf4j
@Activate(
        group = {CommonConstants.PROVIDER, CommonConstants.CONSUMER},
        order = Integer.MAX_VALUE)
public class SaTokenDubbo3Filter implements Filter {


    @Override

    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        String client = RpcContext.getServerContext().isConsumerSide() ?
                CommonConstants.CONSUMER :
                CommonConstants.PROVIDER;
        Result result = null;
        long startTime = 0;
        long elapsed = 0;
        String interFaceLog = "Client[" + client + "],InterfaceName=[" + invocation.getInvoker().getInterface().getSimpleName() + "],MethodName=[" + invocation.getMethodName() + "]";
        log.info("Dubbo-服务调用:{},params:{}", interFaceLog, invocation.getArguments());
        if (RpcContext.getServerContext().isConsumerSide()) {
            //  如果是消费端 设置idtoken到上下文,用于提供者校验
            log.info("SaSameUtil.getToken()--{}", SaSameUtil.getToken());
            log.info("Dubbo-服务调用->设置rpc参数");
            RpcContext.getServiceContext().setAttachment(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken());
            if (SaManager.getSaTokenContextOrSecond() != SaTokenContextDefaultImpl.defaultContext) {
                //赋值token值 获取当前请求的 token 值 （不裁剪前缀）
                RpcContext.getServiceContext().setAttachment("JUST_CREATED_", StpUtil.getTokenValueNotCut());
            }
            log.info("Dubbo-服务调用->获取token值:{}", StpUtil.getTokenValue());
            //设置token到工具类中   纯token 没有前缀

        } else {
            log.info("当前rpc提供者");
            //提供者 校验token
            String idToken = invocation.getAttachment(SaSameUtil.SAME_TOKEN);
            log.info("idToken:{}", idToken);
            if (idToken == null) {
                idToken = invocation.getAttachment(SaSameUtil.SAME_TOKEN.toLowerCase());
                log.info("token为空,重新设置idToken:{}", idToken);
            }
            String token = RpcContext.getServiceContext().getAttachment("JUST_CREATED_");
            log.info("Dubbo-服务调用,开始检验参数:idToken:{},token:{}", idToken, token);
            SaUtil.rpcCheck(idToken, token);
        }
        startTime = System.currentTimeMillis();
        result = invoker.invoke(invocation);
        elapsed = System.currentTimeMillis() - startTime;
        if (result.hasException() && invoker.getInterface().equals(GenericService.class)) {
            log.error("Dubbo-调用异常: {},Exception={}", interFaceLog, result.getException());
        } else {
            log.error("Dubbo-调用成功: SpendTime=[{}ms]", elapsed);
        }
        //用户信息
        log.error("Dubbo-调用完成");
        //注意 不能清空上下文信息 否则其他程序拿不到
//        UserContextHolder.removeUser();
//        SatokenContext.removeLoginType();
        return result;
    }
}



